home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2001 / MacHack 2001.toast / pc / Sessions / Traut / ZStrings / Source / MacOS / MacZString.cpp next >
Encoding:
C/C++ Source or Header  |  2001-06-23  |  11.1 KB  |  446 lines

  1. /*==================================================================
  2.     File:        MacZString.h
  3.  
  4.     Contains:    Mac-specific parsing for ZStrings.
  5.  
  6.     Written by:    Eric Traut
  7.  
  8.     Copyright:    2000-2001 Connectix Corporation
  9.     
  10.     This source has been placed into the public domain by
  11.     Connectix Corporation. You have the right to modify, 
  12.     distribute or use this code without any legal limitations
  13.     or finanicial/licensing requirements. Connectix is not 
  14.     liable for any problems that result from the use of this 
  15.     code.
  16.     
  17.     If you have comments, feedback, questions, or would like
  18.     to submit bug fixes or updates to this code, please email
  19.     opensource@connectix.com.
  20. ==================================================================*/
  21.  
  22. #include <Script.h>
  23.  
  24. #include "MacZString.h"
  25. #include "ZStringDictionary.h"
  26.  
  27. Handle    MacZString::sOverrideHandle = NULL;
  28.  
  29.  
  30. /*------------------------------------------------------------------
  31.     Initialize                                        [static]
  32.  
  33.     This static method instantiates the singleton classes
  34.     for tracking ZStrings.
  35. ------------------------------------------------------------------*/
  36.  
  37. void
  38. MacZString::Initialize()
  39. {
  40.     new ZStringDictionary();
  41.     new MacZStringParser();
  42.     
  43.     sOverrideHandle = NULL;
  44. }
  45.  
  46.  
  47. /*------------------------------------------------------------------
  48.     TearDown                                        [static]
  49. ------------------------------------------------------------------*/
  50.  
  51. void
  52. MacZString::TearDown()
  53. {
  54.     delete &ZStringDictionary::GetZStringDictionary();
  55.     delete &ZStringParser::GetZStringParser();
  56.     
  57.         // Clean up the previously detached override dictionary
  58.     if (sOverrideHandle != NULL)
  59.         ::DisposeHandle(sOverrideHandle);
  60. }
  61.  
  62.  
  63. /*------------------------------------------------------------------
  64.     GetNamedPString                                    [static]
  65. ------------------------------------------------------------------*/
  66.  
  67. void
  68. MacZString::GetNamedPString(
  69.     const char *        inNamedString,
  70.     StringPtr            outPString,
  71.     Z_UInt32            inMaxLength,
  72.     Z_Boolean            inDataIsVolatile)
  73. {
  74.     ZString        namedString;
  75.  
  76.     check(inMaxLength <= 255);
  77.     namedString.GetNamedString(inNamedString, inDataIsVolatile);
  78.     namedString.GetPString(outPString, inMaxLength + 1);
  79. }
  80.  
  81.  
  82. /*------------------------------------------------------------------
  83.     GetNamedPString                                    [static]
  84. ------------------------------------------------------------------*/
  85.  
  86. void
  87. MacZString::GetNamedPString(
  88.     ConstStringPtr        inNamedString,
  89.     StringPtr            outPString,
  90.     Z_UInt32            inMaxLength,
  91.     Z_Boolean            inDataIsVolatile)
  92. {
  93.     char        namedCString[256];
  94.     ZString        namedString;
  95.  
  96.     check(inMaxLength <= 255);
  97.     
  98.     // Copy the input Pascal string into a temporary C string buffer.
  99.     std::memcpy(namedCString, &inNamedString[1], inNamedString[0]);
  100.     namedCString[inNamedString[0]] = '\0';
  101.  
  102.     namedString.GetNamedString(namedCString, inDataIsVolatile);
  103.     namedString.GetPString(outPString, inMaxLength + 1);
  104. }
  105.  
  106.  
  107. /*------------------------------------------------------------------
  108.     LoadOverrideDictionary
  109. ------------------------------------------------------------------*/
  110.  
  111. void
  112. MacZString::LoadOverrideDictionary(
  113.     ResID                inOverrideID)
  114. {
  115.     sOverrideHandle = ::Get1Resource(kZStringOverrideDictionaryResType, inOverrideID);
  116.  
  117.     if (sOverrideHandle != NULL)
  118.     {
  119.         // Detach the resource so that standalone code can close
  120.         // the resource file containing the override dictionary.
  121.         ::DetachResource(sOverrideHandle);
  122.  
  123.         // The resource must remain locked in place because
  124.         // dictionary entries will continue to point to
  125.         // these named strings.
  126.         ::MoveHHi(sOverrideHandle);
  127.         ::HLock(sOverrideHandle);
  128.         ZString::PopulateDictionary((char *)*sOverrideHandle);
  129.  
  130.         Handle            twoByteTable;
  131.         twoByteTable = ::Get1Resource(kZStringTwoByteTableResType, inOverrideID);
  132.  
  133.         // Override the two-byte table if necessary.
  134.         if (twoByteTable != NULL)
  135.         {
  136.             ::HLock(twoByteTable);
  137.             ZStringParser::GetZStringParser().OverrideTwoByteTable((UInt8 *)*twoByteTable);
  138.             ::ReleaseResource(twoByteTable);
  139.         }
  140.     }
  141. }
  142.  
  143.  
  144. /*------------------------------------------------------------------
  145.     CalculateFontInfoBaseID                                [static]
  146.  
  147.     This routine calculates the base resource ID of our 'finf'
  148.     resources. Each language gets up to 16 'finf', and they start
  149.     at a base of 128.
  150. ------------------------------------------------------------------*/
  151.  
  152. ResID
  153. MacZString::CalculateFontInfoBaseID(
  154.     ResID                inOverrideID)
  155. {
  156.     return (inOverrideID - kEnglishOverrideID) * 16 + 128;
  157. }
  158.  
  159.  
  160. /*------------------------------------------------------------------
  161.     CalcOverrideDictionaryID                        [static]
  162.  
  163.     This routine attempts to determine which override dictionary
  164.     the application should use.
  165. ------------------------------------------------------------------*/
  166.  
  167. ResID
  168. MacZString::CalcOverrideDictionaryID()
  169. {
  170.     // First, see if there's a a 'ZLan' resource.
  171.     Handle        lanSpecResource;
  172.     ResID        dictionaryID = 0;
  173.  
  174.     lanSpecResource = ::Get1Resource(kZStringLanguageSpecifierResType, kZStringLanguageSpecifierID);
  175.     if (lanSpecResource != NULL)
  176.     {
  177.         if (::GetHandleSize(lanSpecResource) >= sizeof(UInt16))
  178.             dictionaryID = *(UInt16 *)*lanSpecResource;
  179.  
  180.         ::ReleaseResource(lanSpecResource);
  181.     }
  182.  
  183.     if (dictionaryID == 0)
  184.     {
  185.         // We didn't find a specific language resource,
  186.         // so we need to attempt to determine the ID from
  187.         // the system software.
  188.  
  189.         SInt32        languageCode;
  190.  
  191.         // We'll get the language for the system script.
  192.         // fix me - should we use the "current script" instead?
  193.         languageCode = ::GetScriptVariable(smSystemScript, smScriptLang);
  194.  
  195.         switch (languageCode)
  196.         {
  197.             default:
  198.             case langEnglish:
  199.                 dictionaryID = kEnglishOverrideID;
  200.                 break;
  201.  
  202.             case langFrench:
  203.                 dictionaryID = kFrenchOverrideID;
  204.                 break;
  205.  
  206.             case langGerman:
  207.                 dictionaryID = kGermanOverrideID;
  208.                 break;
  209.  
  210.             case langItalian:
  211.                 dictionaryID = kItalianOverrideID;
  212.                 break;
  213.  
  214.             case langSpanish:
  215.                 dictionaryID = kSpanishOverrideID;
  216.                 break;
  217.  
  218.             case langJapanese:
  219.                 dictionaryID = kJapaneseOverrideID;
  220.                 break;
  221.  
  222.             case langPortuguese:
  223.                 dictionaryID = kPortugueseOverrideID;
  224.                 break;
  225.         }
  226.     }
  227.  
  228.     return dictionaryID;
  229. }
  230.  
  231.  
  232. /*------------------------------------------------------------------
  233.     ExtractMenuInfo                                    [static]
  234. ------------------------------------------------------------------*/
  235.  
  236. UInt8
  237. MacZString::ExtractMenuInfo(
  238.     const char *        inMenuZString,
  239.     Str255                outMenuItemText)
  240. {
  241.     ZString            menuItemDescription;
  242.     ZString            menuItemText;
  243.     ZString            menuItemKey;
  244.     UInt8            menuKey = 0;
  245.  
  246.     menuItemDescription.GetNamedString(inMenuZString);
  247.  
  248.     // Get the two substrings.
  249.     menuItemText = menuItemDescription.GetSubstring(0, '/');
  250.     menuItemKey = menuItemDescription.GetSubstring(1, '/');
  251.  
  252.     menuItemText.GetPString(outMenuItemText);
  253.  
  254.     if (menuItemKey.GetLength() > 0)
  255.     {
  256.         check(menuItemKey.GetLength() == 1);
  257.         menuKey = menuItemKey.GetCString()[0];
  258.     }
  259.  
  260.     return menuKey;
  261. }
  262.  
  263.  
  264. /*------------------------------------------------------------------
  265.     BuildMenu                                        [static]
  266. ------------------------------------------------------------------*/
  267.  
  268. void
  269. MacZString::BuildMenu(
  270.     MenuHandle            inMenuHandle,
  271.     const char **        inMenuInfo,
  272.     Boolean                inInsertMenu)
  273. {
  274.     Str255            menuItemText;
  275.     UInt8            menuKey;
  276.     UInt32            infoIndex = 0;
  277.     const char *    curMenuItemInfo;
  278.     UInt16            itemIndex = 1;
  279.  
  280.     while (inMenuInfo[infoIndex] != NULL)
  281.     {
  282.         curMenuItemInfo = inMenuInfo[infoIndex];
  283.  
  284.         // Is this a divider?
  285.         if (curMenuItemInfo[0] == 0)
  286.         {
  287.             ::AppendMenu(inMenuHandle, "\p-");
  288.             ::DisableMenuItem(inMenuHandle, itemIndex);
  289.         }
  290.         else
  291.         {
  292.             menuKey = ExtractMenuInfo(curMenuItemInfo, menuItemText);
  293.  
  294.             // Append the new item. We don't send the text directly
  295.             // in to AppendMenu because it may interpret some of the
  296.             // special characters as code for command keys, etc.
  297.             ::AppendMenu(inMenuHandle, "\p ");
  298.             ::SetMenuItemText(inMenuHandle, CountMenuItems(inMenuHandle), menuItemText);
  299.  
  300.             if (menuKey != 0)
  301.                 ::SetItemCmd(inMenuHandle, itemIndex, menuKey);
  302.         }
  303.  
  304.         infoIndex++;
  305.         itemIndex++;
  306.     }
  307.  
  308.     // Insert into the menu bar at the end.
  309.     if (inInsertMenu)
  310.         ::InsertMenu(inMenuHandle, 0);
  311. }
  312.  
  313.  
  314. /*------------------------------------------------------------------
  315.     ReplaceParameter
  316. ------------------------------------------------------------------*/
  317.  
  318. ZString
  319. MacZString::ReplaceParameter(
  320.     Z_UInt8                inParamNum,
  321.     ConstStringPtr        inString)
  322. {
  323.     char    cString[256];
  324.  
  325.     // Copy the input Pascal string into a temporary C string buffer.
  326.     std::memcpy(cString, &inString[1], inString[0]);
  327.     cString[inString[0]] = '\0';
  328.  
  329.     return ZString::ReplaceParameter(inParamNum, cString);
  330. }
  331.  
  332. /*------------------------------------------------------------------
  333.     GetTagReplacement
  334. ------------------------------------------------------------------*/
  335.  
  336. UInt16
  337. MacZStringParser::GetTagReplacement(
  338.     ZStringTagID                inTagID,
  339.     char *                        outReplacement)
  340. {
  341.     // By default, all tags are one character.
  342.     UInt16        tagSize = 1;
  343.  
  344.     if (outReplacement != NULL)
  345.     {
  346.         static const char    sTagReplacements[] = {
  347.             '\0',                // kTagIDInvalid
  348.             0xAE,                // kZTag_AElig,
  349.             0xE7,                // kZTag_Aacute,
  350.             0xE5,                // kZTag_Acirc,
  351.             0xCB,                // kZTag_Agrave,
  352.             0x81,                // kZTag_Aring,
  353.             0xCC,                // kZTag_Atilde,
  354.             0x80,                // kZTag_Auml,
  355.             0x82,                // kZTag_Ccedil,
  356.             0x83,                // kZTag_Eacute,
  357.             0xE6,                // kZTag_Ecirc,
  358.             0xE9,                // kZTag_Egrave,
  359.             0xE8,                // kZTag_Euml,
  360.             0xEA,                // kZTag_Iacute,
  361.             0xEB,                // kZTag_Icirc,
  362.             0xED,                // kZTag_Igrave,
  363.             0xEC,                // kZTag_Iuml,
  364.             0x84,                // kZTag_Ntilde,
  365.             0xEE,                // kZTag_Oacute,
  366.             0xEF,                // kZTag_Ocirc,
  367.             0xF1,                // kZTag_Ograve,
  368.             0xAF,                // kZTag_Oslash,
  369.             0xCD,                // kZTag_Otilde,
  370.             0x85,                // kZTag_Ouml,
  371.             0xF2,                // kZTag_Uacute,
  372.             0xF3,                // kZTag_Ucirc,
  373.             0xF4,                // kZTag_Ugrave,
  374.             0x86,                // kZTag_Uuml,
  375.             0x87,                // kZTag_aacute,
  376.             0x89,                // kZTag_acirc,
  377.             0xBE,                // kZTag_aelig,
  378.             0x88,                // kZTag_agrave,
  379.             0x26,                // kZTag_amp,
  380.             0x8C,                // kZTag_aring,
  381.             0x8B,                // kZTag_atilde,
  382.             0x8A,                // kZTag_auml,
  383.             0xE3,                // kZTag_bdquo,
  384.             0xA5,                // kZTag_bull,
  385.             0x8D,                // kZTag_ccedil,
  386.             0xA2,                // kZTag_cent,
  387.             0xA9,                // kZTag_copy,
  388.             0x8E,                // kZTag_eacute,
  389.             0x90,                // kZTag_ecirc,
  390.             0x8F,                // kZTag_egrave,
  391.             0x91,                // kZTag_euml,
  392.             0x3E,                // kZTag_gt,
  393.             0xC9,                // kZTag_hellip,
  394.             0x92,                // kZTag_iacute,
  395.             0x94,                // kZTag_icirc,
  396.             0xC1,                // kZTag_iexcl,
  397.             0x92,                // kZTag_igrave,
  398.             0xC0,                // kZTag_iquest,
  399.             0x95,                // kZTag_iuml,
  400.             0xD2,                // kZTag_ldquo,
  401.             0xD4,                // kZTag_lsquo,
  402.             0x3C,                // kZTag_lt,
  403.             0xD1,                // kZTag_mdash,
  404.             0xB5,                // kZTag_micro,
  405.             0xCA,                // kZTag_nbsp,
  406.             0xD0,                // kZTag_ndash,
  407.             0x96,                // kZTag_ntilde,
  408.             0x97,                // kZTag_oacute,
  409.             0x99,                // kZTag_ocirc,
  410.             0x98,                // kZTag_ograve,
  411.             0xBF,                // kZTag_oslash,
  412.             0x9B,                // kZTag_otilde,
  413.             0x9A,                // kZTag_ouml,
  414.             0xA6,                // kZTag_para,
  415.             0xB9,                // kZTag_pi,
  416.             0xA3,                // kZTag_pound,
  417.             0xD3,                // kZTag_rdquo,
  418.             0xA8,                // kZTag_reg,
  419.             0x00,                // kZTag_replace
  420.             0xD5,                // kZTag_rsquo,
  421.             0xE2,                // kZTag_sbquo,
  422.             0xA7,                // kZTag_szlig,
  423.             0xAA,                // kZTag_trade,
  424.             0x9C,                // kZTag_uacute,
  425.             0x9E,                // kZTag_ucirc,
  426.             0x9D,                // kZTag_ugrave,
  427.             0x9F,                // kZTag_uuml,
  428.             0xB4,                // kZTag_yen,
  429.             0xD8,                // kZTag_yuml
  430.             0x0D                // kZTag_br
  431.         };
  432.  
  433.         check(inTagID > kZTag_Invalid && inTagID < sizeof(sTagReplacements));
  434.         check(inTagID != kZTag_replace);
  435.  
  436.         // fill in the equivalent
  437.         *outReplacement = sTagReplacements[inTagID];
  438.     }
  439.  
  440.     return tagSize;
  441. }
  442.  
  443.  
  444.  
  445.  
  446.